package org.hxzon.demo.juntai.csserver.server;

import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Executor;

import org.hxzon.demo.juntai.csserver.common.Config;
import org.hxzon.project.AppRuntimeException;

public class MyServerHandler implements Runnable {

    private String message;
    private ByteBuffer bufReceive = ByteBuffer.allocate(Config.maxByteBuffer);
    boolean first = true;
    private int countTotalRead = 0;
    int lenParam = 0;

    private Executor executor;
    private SelectionKey key;

    public MyServerHandler(Executor executor) {
        this.executor = executor;
    }

    public void handle(SelectionKey key) {
        if(key.isReadable()||key.isWritable()){
            executor.execute(this);
        }
    }

    //
    public void run() {
        Util.debug("key:" + key);
        try {
            if (key.isReadable()) {
                key.interestOps(key.interestOps() & (~SelectionKey.OP_READ));//?

                SocketChannel scRead = (SocketChannel) key.channel();
                if (first) {
                    bufReceive.clear();
                }
                int count = -1;
                do {
                    count = scRead.read(bufReceive);
                    Util.debug("read count:" + count);
                    countTotalRead += count;
                } while (count > 0);

                //
                if (first) {
                    //if first,read header
                    ByteBuffer bufTmp = bufReceive.duplicate();
                    bufTmp.flip();
                    first = false;
                    lenParam = bufTmp.getInt();
                }

                //
                if (countTotalRead == lenParam + 4) {
                    Util.debug("read complete");
                    //can write only after read complete
                    Util.registerChannel(key.selector(), scRead, SelectionKey.OP_WRITE, this);
                    //
                    bufReceive.flip();
                    bufReceive.getInt();//len
                    message = Util.readString(bufReceive);
                    Util.println(message);
                    //reset for new request
                    lenParam = 0;
                    countTotalRead = 0;
                    first = true;
                    //return;
                } else {
                    Util.debug("read not complete,countTotalRead:" + countTotalRead + ",want:" + (lenParam + 4));
                    //will be remove,so register again
                    Util.registerChannel(key.selector(), scRead, SelectionKey.OP_READ, this);
                    //key.selector().select(Config.timeout_select);//?
                    key.interestOps(key.interestOps() | SelectionKey.OP_READ);//?
                    key.selector().wakeup();
                }
            }
            if (key.isWritable()) {
                Util.debug("send msg");
                SocketChannel scWrite = (SocketChannel) key.channel();
                ByteBuffer bufSend = bufReceive;
                bufSend.clear();
                Util.putString("echo:" + message, bufSend);
                bufSend.flip();
                scWrite.write(bufSend);
                Util.registerChannel(key.selector(), scWrite, SelectionKey.OP_READ, this);
            }
        } catch (Exception e) {
            throw AppRuntimeException.rethrow(e);
            //Util.println(e);
        }
    }
}
